package se.thoka.twt.client.utils;

public enum TimeUnit {
	WEEKS(DateTimeUtil.WEEK_IN_MILLIS, null, 1, "", false),
	DAYS(DateTimeUtil.DAY_IN_MILLIS, WEEKS, 1, ":", false),
	HOURS(DateTimeUtil.HOUR_IN_MILLIS, DAYS, 2, ":", true),
	MINUTES(DateTimeUtil.MINUTE_IN_MILLIS, HOURS, 2, ":", true),
	SECONDS(DateTimeUtil.SECOND_IN_MILLIS, MINUTES, 2, ":", false),
	MILLIS(1, SECONDS, 3, ".", false);
	
	private final long millis;
	private final TimeUnit ceilUnit;
	private final int minStrLen;
	private final String formatDivider;
	private final boolean zeroPadOnFirst;
	private TimeUnit(long millis, TimeUnit ceilUnit, int minStrLen, String formatDivider, boolean zeroPadOnFirst) {
		this.millis = millis;
		this.ceilUnit = ceilUnit;
		this.minStrLen = minStrLen;
		this.formatDivider = formatDivider;
		this.zeroPadOnFirst = zeroPadOnFirst;
	}
	
	public long getMillis() {
		return millis;
	}
	
	public long getMillis(long nbr) {
		return nbr * millis;
	}
	
	public long getAsUnit(long millis) {
		return getAsUnit(millis, false);
	}
	
	public long getAsUnit(long millis, boolean distinct) {
		long result;
		if (ceilUnit != null && distinct) {
			result = ceilUnit.subtractUnitMillis(millis) / this.millis;
		} else {
			result = millis / this.millis;
		}
		
		return result;
	}
	
	public String format(long millis) {
		return format(millis, false);
	}
	
	public String format(long millis, boolean greedy) {
		return format(millis, null, greedy);
	}
	public String format(long millis, TimeUnit limitUnit) {
		return format(millis, limitUnit, false);
	}
	
	public String format(final long millis, TimeUnit limitUnit, boolean greedy) {
		StringBuilder sb = new StringBuilder();
		boolean appended = false;
		boolean limited = limitUnit != null;
		int startOrd = Math.min(ordinal(), limited ? limitUnit.ordinal() : 0);
		int stopOrd = Math.max(ordinal(), limited ? limitUnit.ordinal() : values().length);
		for (TimeUnit unit : values()) {
			if (limited) {
				if (unit.ordinal() < startOrd) {
					continue;
				} else if (unit.ordinal() > stopOrd) {
					break;
				}
			}
			long value = unit.getAsUnit(millis, unit.ordinal() != startOrd);
			boolean lastUnit = unit.ordinal() == stopOrd;
			if (lastUnit || greedy || !limited || (appended || value > 0)) {
				if (appended) {
					sb.append(unit.formatDivider);
				}
				long millisLeftAfter = unit.subtractUnitMillis(millis);
				boolean zeroPad = appended || (unit.zeroPadOnFirst && millisLeftAfter != 0);
				sb.append(zeroPad ? StringUtils.zeroPad(value, unit.minStrLen) : value);
				appended = true;
			}
		}
		
		return sb.toString();
	}
	
	public long subtractUnitMillis(long millis) {
		return millis % this.millis;
	}
	
//	public static void main(String[] args) {
//		long testMillis = HOURS.getMillis(4) + MINUTES.getMillis(5) + SECONDS.getMillis(6) + 789;
//		for (TimeUnit unit : values()) {
//			for (TimeUnit limitUnit : values()) {
//				testFormat(unit, testMillis, limitUnit, false);
//			}
//		}
//		
//	}
//	
//	private static void testFormat(TimeUnit unit, long millis, TimeUnit limit, boolean greedy) {
//		
//		System.out.println(millis + ", " + unit.name() + ", " + limit + ", " + greedy + "\t" + unit.format(millis, limit, greedy));
//	}
}
